package de.ars.client.datahandling;

import java.util.Vector;

import com.sun.lwuit.Font;

public class StringSplitter {
	
	private static final char HYPHEN = '~';
	
	protected static boolean lineTooWide( Font font, int curLineLength,char curChar, int lineWidth )
    {
        return curLineLength + font.charWidth(curChar) > lineWidth;
    }
	
	public static String[] splitLabel( Font font, String input, int lineWidthFirstPart)
    {
    	return splitLabel(font,input,lineWidthFirstPart,-1,-1);
    }
	
	public static String[] splitLabel( Font font, String input, int lineWidthFirstPart,int heightFirstPart,int lineWidthSecondPart )
    {
        /* The idea of this algorithm is to run once to the input text and process each character.
         * a) When a hyphen (HYPHEN), dash or space is found, the current position is marked (lastWrap).
         * b) A new line character in the input string terminates the current line (which is then
         *    pushed to a vector) and a new line starts.
         * c) Any other character is just copied to the current line.
         *
         * When a line becomes too wide, the line is wrapped at the last known position (lastWrap).
         * If there is no such position known, the line is simply wrapped at the current position.
         */

        Vector allLines = new Vector(); // takes lines once they are completly processed, later it is converted to String[]
        StringBuffer curLine = new StringBuffer( "" ); // takes characters of the current line without any dashes, hyphen, etc.

        int fontHeight = font.getHeight();
        int overallHeight = 0;
        
        int lastWrapIndex = 0; // the last (most right) index pos at which curLine can be wrapped
        char lastWrapChar = '-'; // the character that should be used for wrapping
        int startOverInInput = 0; // the index pos in input where a new line should be started
        int curIndex = 0; // the current position in curLine, starts with 0 in a new line
        char curChar; // the character which is currently processed
        int curLineLength = 0;

        boolean actionLineWrap = false; // set to true to indicate that the current line is too long at should be wrapped
        boolean actionAppendChar = false; // set to true to indicate that the current line is not too long and the next character should be just copied
        boolean actionNewLine = false; // set to true to indicate that the current line processed and a new line should be started

        int i = 0; // the index pos in input, starts with 0 and runs thru all characters

        try
        {
            /* Process all characters in the input sequentially. */
            while( i < input.length() )
            {
                /* Get the character at position i. */
                curChar = input.charAt( i );

                /* If its is a hyphen and the current line with a dash would be too long,
                 * wrap the line at the last (!) known wrap postion.
                 */
                if( curChar == HYPHEN && lineTooWide( font, curLineLength, '-', lineWidthFirstPart ) )
                {
                    actionLineWrap = true;
                }

                /* If its ia hyphen and the line would NOT be too wide even with the dash
                 * (the hyphen is now translated to a dash), this position is marked.
                 */
                else if( curChar == HYPHEN && !lineTooWide( font, curLineLength, '-', lineWidthFirstPart ) )
                {
                    lastWrapIndex = curIndex; // The position for wrapping is the current position.
                    lastWrapChar = '-'; // If this position is used for wrapping, a dash has to be appended
                    // to the current line.
                    startOverInInput = i; // The next line is started with the next character.
                }

                /* If it is a space or a TAB or a CR, the current position is marked. The current character
                 * is translated to a space in all cases.
                 */
                else if( curChar == ' ' || curChar == '\t' || curChar == '\r' )
                {
                    actionAppendChar = true; // Although this is a wrap position, we need the space
                    curChar = ' ';
                    lastWrapIndex = curIndex;
                    lastWrapChar = ' '; // If this position is used for wrapping, a space has to be appended
                    // to the current line, which is later trimmed again.
                    startOverInInput = i; // The next line is started with the next character.
                }

                /**
                 * If its a dot character, mark the current position as possible
                 * wrap position.
                 */
                else if( curChar == '.' )
                {
                    actionAppendChar = true;
                    lastWrapIndex = curIndex;
                    lastWrapChar = '.'; // If this position is used for wrapping, a space has to be appended
                    // to the current line, which is later trimmed again.
                    startOverInInput = i; // The next line is started with the next character.
                }

                /* If it is a new line character, a new line is started -- funny, eh?
                 */
                else if( curChar == '\n' )
                {
                    actionNewLine = true;
                    startOverInInput = i; // The next line is started with the next character.
                }

                /* If its is a dash and the current line with a dash would be too long,
                 * wrap the line at the last (!) known wrap postion.
                 */
                else if( curChar == '-' && lineTooWide( font, curLineLength, '-', lineWidthFirstPart ) )
                {
                    actionLineWrap = true;
                }

                /* If its a dash and the line would NOT be too wide even with the dash,
                 * this position is marked.
                 */
                else if( curChar == '-' && !lineTooWide( font, curLineLength, '-', lineWidthFirstPart ) )
                {
                    actionAppendChar = true; // The dash is still appended to the current line.
                    lastWrapIndex = curIndex + 1; // The position for wrapping is the NEXT character (after the dash!).
                    lastWrapChar = ' '; // In this wrap position is used, only a space has to be appended.
                    startOverInInput = i; // The next line is started with the next character.
                }

                /* If it is a plain character and the line would NOT be to wide with it, just append the character.
                 */
                else if( !lineTooWide( font, curLineLength, curChar, lineWidthFirstPart ) )
                {
                    actionAppendChar = true;
                }

                /* If it is a plain character, but the line would be too wide with it, wrap the line at
                 * the last known position.
                 */
                else if( lineTooWide( font, curLineLength, curChar, lineWidthFirstPart ) )
                {
                    actionLineWrap = true;
                }

                /* If a line wrap was requested. */
                if( actionLineWrap )
                {
                    /* If a wrap position is known, i.e. the current line contains a space, dash or it had a hyphen. */
                    if( lastWrapIndex != 0 )
                    {
                        /* Add the current line to the vector of processed lines. Before, add the previously defined wrap
                         * character.
                         */
                        allLines.addElement( new StringBuffer()
                                .append( curLine.toString().substring( 0, lastWrapIndex ) ).append( lastWrapChar )
                                .toString().trim() );

                        /* Reset some variables to be ready for a new line. */
                        lastWrapIndex = 0;
                        i = startOverInInput; // We set i (the current pos in the input) to the last character of the
                        // current line. As i is incremented later, the new line will start with
                        // the first character after the wrap position.
                    }

                    /* Otherwise, i.e. if no wrap position was marked before. */
                    else
                    {

                        /* Add the current line to the vector of processed lines. */
                        allLines.addElement( curLine.toString().trim() );

                        /* The current character is the first one that belongs to the next line. Therefore,
                         * we skip back one character and make the outer loop process this character again.
                         */
                        i--;

                    }

                    if (heightFirstPart > -1)
                    {
	                    overallHeight += fontHeight;
	                    if (overallHeight > heightFirstPart)
	                    	lineWidthFirstPart = lineWidthSecondPart;
                    }
                    /* Reset some variables before processing the new line. */
                    curLine = new StringBuffer();
                    startOverInInput = 0;
                    curLineLength = 0;
                    curIndex = 0;
                }

                /* If it was requested just to add the current character, just append it to the current line and
                 * incremente the position in the current line.
                 */
                else if( actionAppendChar )
                {
                    curLine.append( curChar );
                    curLineLength += font.charWidth(curChar);
                    curIndex++;
                }

                /* If a new line has to be created (because of a new line character). */
                else if( actionNewLine )
                {
                    /* If the new line comes immediately after the last marked wrap position, e.g.
                     * "AAB=\n", then add the wrap character. Otherwise, don't add a wrap character, because there
                     * were other characters such as in "AAB=C\n", which results in "AABC". */
                    if( i - 1 == lastWrapIndex )
                    {
                        curLine.append( lastWrapChar );
                    }

                    /* The current line is trimmed before adding it to the vector. ATTENTION, even
                     * leading white spaces are deleted!
                     */
                    allLines.addElement( curLine.toString().trim() );

                    /* Reset some variables in order to prepare processing of the next line. */
                    curIndex = 0;
                    curLine = new StringBuffer();
                    curLineLength = 0;
                }

                /* Delete all action varialbes, so that a new line can be processed. */
                actionLineWrap = false;
                actionAppendChar = false;
                actionNewLine = false;

                /* Increment the current position in the input string. */
                i++;

            }

            /* Push last line into vector */
            allLines.addElement( curLine.toString() ); // do not trim here, because the last space should be visible!

            /* Copy the vector elements to a String array. */
            String[] result = new String[allLines.size()];
            allLines.copyInto( result );

            /* And finally return the String array. */
            return result;
        }
        catch( Exception e )
        {
            /* In case of any exception, we try to apply an easier form of line wrapping. */
            try
            {
                i = 0;

                while( i < input.length() )
                {
                    /* Get the character at position i. */
                    curChar = input.charAt( i );

                    switch( curChar )
                    {
                        case '\n':
                            allLines.addElement( curLine.toString().trim() );
                            curLine = new StringBuffer();
                            curLineLength = 0;
                            break;
                        case '\t':
                        case '\r':
                        case HYPHEN:
                            break;
                        default:
                            if( lineTooWide( font, curLineLength, curChar, lineWidthFirstPart ) )
                            {
                                allLines.addElement( curLine.toString().trim() );
                                curLine = new StringBuffer();
                                curLineLength = 0;
                            }

                            curLine.append( curChar );
                            curLineLength += font.charWidth(curChar);
                            break;
                    }

                    i++;
                }

                allLines.addElement( curLine.toString().trim() );

                /* Copy the vector elements to a String array. */
                String[] result = new String[allLines.size()];
                allLines.copyInto( result );

                /* And finally return the String array. */
                return result;
            }
            catch( Exception e1 )
            {
                /* If even this easier version doesn't work, we give up. */
                //e1.printStackTrace( );
                return new String[] { "Fehler" };
            }
        }
    }
}